package master.ghrm.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
import javax.persistence.Version;

/**
 * Evaluation Answer
 */
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Answer extends AbstractBaseEntity {
	private static final long serialVersionUID = 1L;

	private static final String[] EXCL_ATTR = { "version" };

	public static final int COMMENT_LENGTH = 240;
	public static final int ELABORATION_LENGTH = 2000;

	private Long version;
	private Integer answerId;
	private String elaboration;
	private Assessment assessment;

	/**
	 * Default constructor, for persistence use.
	 */
	public Answer() {
	}

	/**
	 * @return ID.
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "answer_id")
	public Integer getAnswerId() {
		return this.answerId;
	}

	/**
	 * For persistence use.
	 * 
	 * @param anAnswerId ID.
	 */
	public void setAnswerId(Integer anAnswerId) {
		this.answerId = anAnswerId;
	}

	/**
	 * For persistence use.
	 * 
	 * @return the version
	 */
	@Version
	Long getVersion() {
		return this.version;
	}

	/**
	 * For persistence use.
	 * 
	 * @param aVersion the version to set
	 */
	void setVersion(Long aVersion) {
		this.version = aVersion;
	}

	/**
	 * @return the elaboration
	 */
	@Column(length = Answer.ELABORATION_LENGTH, nullable = true)
	public String getElaboration() {
		return this.elaboration;
	}

	/**
	 * @param anElaboration the elaboration to set
	 */
	public void setElaboration(String anElaboration) {
		this.elaboration = anElaboration;
	}

	/**
	 * @return assessment.
	 */
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "assessment_id", nullable = false)
	public Assessment getAssessment() {
		return this.assessment;
	}

	/**
	 * @param anAssessment assessment.
	 */
	public void setAssessment(Assessment anAssessment) {
		this.assessment = anAssessment;
	}

	/**
	 * Get the question for this answer.
	 * 
	 * @return question of this answer.
	 */
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "question_id", nullable = false)
	public abstract Question getQuestion();

	public abstract void setQuestion(Question question);

	/**
	 * This is a standard {@link Object#toString()}, but it is re-declared as abstract, to force each child class to
	 * implement it properly.
	 * 
	 * @return textual representation of the answer.
	 * @see Object#toString()
	 */
	@Override
	public abstract String toString();

	/**
	 * @return array of additional attributes to exclude.
	 */
	@Transient
	protected abstract String[] getAdditionalExclAttr();

	/**
	 * Concatenate base exclude attributes and additional ones.
	 * 
	 * @return complete array of exclude attributes.
	 * @see #getAdditionalExclAttr()
	 */
	@Override
	@Transient
	protected String[] getExcludedAttributes() {
		String[] additional = this.getAdditionalExclAttr();
		if (additional == null || additional.length == 0) {
			return Answer.EXCL_ATTR;
		}
		String[] result = new String[Answer.EXCL_ATTR.length + additional.length];
		for (int i = 0; i < Answer.EXCL_ATTR.length; ++i) {
			result[i] = Answer.EXCL_ATTR[i];
		}
		for (int i = 0; i < additional.length; ++i) {
			result[Answer.EXCL_ATTR.length + i] = additional[i];
		}
		return result;
	}
}
